package com.gm.math;

import Jama.Matrix;


/**
 * Created by Mouse on 2017/8/4.
 */
public class CovarianceMatrix {

    Matrix srcMatrix;

    public CovarianceMatrix(Matrix srcMatrix) {
        this.srcMatrix = srcMatrix;
    }


    public Matrix toCovarianceMatrix() {

        //初始化列矩阵与均值
        Matrix[] matrixsColumns = new Matrix[srcMatrix.getColumnDimension()];
        double[] avgColumns = new double[srcMatrix.getColumnDimension()];
        for (int i = 0; i < matrixsColumns.length; i++) {
            matrixsColumns[i] = srcMatrix.getMatrix(0, srcMatrix.getRowDimension() - 1, i, i);
            avgColumns[i] = avg(matrixsColumns[i]);
        }

        //列矩阵转换均差矩阵
        for (int i = 0; i < matrixsColumns.length; i++) {
            Matrix matrix = matrixsColumns[i];
            double avg = avgColumns[i];
            averageDeviationMatrix(matrix, avg);
        }

        //协方差矩阵
        double[][] covMatrix = new double[matrixsColumns.length][matrixsColumns.length];
        for (int i = 0; i < matrixsColumns.length; i++) {
            for (int j = 0; j < matrixsColumns.length; j++) {
                covMatrix[i][j] = cov(matrixsColumns[i], matrixsColumns[j], srcMatrix.getRowDimension() - 1);
            }
        }

        return new Matrix(covMatrix);
    }

    private double avg(Matrix m) {
        int n = m.getRowDimension() * m.getColumnDimension();
        double sum = 0;
        for (int i = 0; i < m.getRowDimension(); i++)
            for (int j = 0; j < m.getColumnDimension(); j++)
                sum += m.getArray()[i][j];
        return sum / n;
    }

    private double cov(Matrix matrixI, Matrix matrixJ, int size) {
        Matrix a = matrixI.transpose().times(matrixJ);
        return a.det() / size;
    }

    private void averageDeviationMatrix(Matrix matrixCol, double avg) {
        for (int i = 0; i < matrixCol.getRowDimension(); i++) {
            for (int j = 0; j < matrixCol.getColumnDimension(); j++) {
                double v = matrixCol.get(i, j);
                matrixCol.set(i, j, v - avg);
            }
        }
    }


}
